ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
MailDelivery.c
Go to the documentation of this file.
00001 
00017 #include "derivative.h"
00018 #include "Compile_Options.h"
00019 #include "MailDelivery.h"
00020 #include "eDMA.h"
00021 #include "DSPI.h"
00022 /*
00023  ******************************************************************************
00024  * Constants
00025  ******************************************************************************
00026  */
00027 
00028 /*
00029  ******************************************************************************
00030  * Globals
00031  ******************************************************************************
00032  */
00034 vuint32_t gau32DSPIOutbox[(OUTBOX_MAX_BUFFER_CNT + 1u) * 2u];
00036 TCD_t    gatDSPIInbox[INBOX_MAX_BUFFER_CNT * 2u]; /* Today this is 4K */
00038 vuint8_t gu8MailboxActiveOutboxOffset;
00040 vint8_t gi8MailboxActiveInboxOffset;
00042 vuint8_t gu8InboxDMA;
00044 vuint8_t gu8InactiveInboxDMA;
00046 vuint8_t gu8OutboxDMA;
00048 vuint8_t gu8InactiveOutboxDMA;
00049 /*
00050  ******************************************************************************
00051  * u8fnMailDeliveryOfOutboxInit
00052  ******************************************************************************
00053  */
00054 uint8_t u8fnMailDeliveryOfOutboxInit(uint32_t* pu32Outbox,
00055                                      uint32_t* pu32Output, uint8_t u8DMAChannel)
00056 {
00057   TCD_t tMyDefaultConfig;
00058     
00059   /* Outbox always has the size in its first address. Compensate for this */
00060   tMyDefaultConfig.P.SADDR = ((uint32_t)pu32Outbox + 4u);
00061   /* Destination address is our output vehicle (DSPI, for example) */
00062   tMyDefaultConfig.P.DADDR = (uint32_t)pu32Output;
00063   /* Modulus is 0 */
00064   tMyDefaultConfig.P.SMOD = CLEAR;
00065   tMyDefaultConfig.P.DMOD = CLEAR;
00066   /* We will transfer 32-bit words */
00067   tMyDefaultConfig.P.SSIZE = DMA_SIZE_32_BIT;
00068   tMyDefaultConfig.P.DSIZE = DMA_SIZE_32_BIT;
00069   tMyDefaultConfig.P.SOFF = 4u; /* Offset per minor loop (in bytes) */
00070   tMyDefaultConfig.P.DOFF = 0u; /* Destination offset per minor loop */
00071   tMyDefaultConfig.P.NBYTES = 4u; /* Inner loop transfer count (in bytes) */
00072   tMyDefaultConfig.P.SLAST = CLEAR;
00073   tMyDefaultConfig.P.CITERE_LINK = CLEAR;
00074   tMyDefaultConfig.P.BITERE_LINK = CLEAR;
00075   tMyDefaultConfig.P.CITER = 0u; /* Times we'll execute our minor loop */
00076   tMyDefaultConfig.P.BITER = 0u; /* Memory for the loop */
00077   tMyDefaultConfig.P.D_REQ = TRUE; /* Clear HW Start requests after major loop is done */
00078   
00079   tMyDefaultConfig.P.DLAST_SGA = CLEAR; /* Last destination offset */
00080   tMyDefaultConfig.P.MAJORLINKCH = CLEAR;
00081   tMyDefaultConfig.P.BWC = DMA_BWC_4_CYCLE_STALL;
00082   tMyDefaultConfig.P.MAJORE_LINK = CLEAR; /* Disable ch2ch linking */
00083   tMyDefaultConfig.P.E_SG = CLEAR;
00084   
00085   /* EDMA's DONE bit must be set to take the interrupt. This will be */
00086   /* updated as necessary, but for now, set it.                      */
00087   tMyDefaultConfig.P.DONE = TRUE;
00088   
00089   tMyDefaultConfig.P.INT_HALF = CLEAR;
00090   tMyDefaultConfig.P.INT_MAJ = CLEAR; /* No ISR for Outbox done */
00091   tMyDefaultConfig.P.START = CLEAR;
00092   
00093   vfnDMAConfig(&tMyDefaultConfig, u8DMAChannel);
00094   
00095   /* Config DMAMux to go along with it */
00096   vfnDMAMUXInit(u8DMAChannel, DMA_SOURCE_DSPI0_TX, CLEAR, TRUE);
00097   
00098   /* Remember which is the initial DMA we're using */
00099   gu8OutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH;
00100   gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH;
00101   
00102   return (CLEAR);
00103 }
00104 /*
00105  ******************************************************************************
00106  * u8fnMailDeliveryToInboxInit
00107  ******************************************************************************
00108  */
00109 uint8_t u8fnMailDeliveryToInboxInit(uint16_t* pu16Input)
00110 {
00111   uint8_t u8Counter;
00112   TCD_t tMyDefaultConfig;
00113   
00114   
00115   tMyDefaultConfig.P.SADDR = (uint32_t)pu16Input;
00116   tMyDefaultConfig.P.DADDR = (uint32_t)CLEAR;
00117   tMyDefaultConfig.P.SMOD = CLEAR;
00118   tMyDefaultConfig.P.DMOD = CLEAR;
00119   tMyDefaultConfig.P.SSIZE = DMA_SIZE_16_BIT;
00120   tMyDefaultConfig.P.DSIZE = DMA_SIZE_16_BIT;
00121   tMyDefaultConfig.P.SOFF = 0u; /* Offset per minor loop (in bytes) */
00122   tMyDefaultConfig.P.DOFF = 2u; /* Destination offset per minor loop */
00123   tMyDefaultConfig.P.NBYTES = 2u; /* Inner loop transfer count (in bytes) */
00124   tMyDefaultConfig.P.SLAST = CLEAR;
00125   tMyDefaultConfig.P.CITERE_LINK = CLEAR;
00126   tMyDefaultConfig.P.BITERE_LINK = CLEAR;
00127   tMyDefaultConfig.P.CITER = 0u; /* Times we'll execute our minor loop */
00128   tMyDefaultConfig.P.BITER = 0u; /* Memory for the loop */
00129   
00130   tMyDefaultConfig.P.DLAST_SGA = CLEAR; /* By default, zero. This will change with lnking */
00131   tMyDefaultConfig.P.MAJORLINKCH = MAILDELIVERY_INBOX1_DMA_CH;
00132   tMyDefaultConfig.P.BWC = DMA_BWC_4_CYCLE_STALL;
00133   tMyDefaultConfig.P.MAJORE_LINK = CLEAR; /* Disable ch2ch linking */
00134   tMyDefaultConfig.P.E_SG = CLEAR;
00135   tMyDefaultConfig.P.D_REQ = CLEAR; /* Will be modified as the stack grows */
00136   tMyDefaultConfig.P.INT_HALF = CLEAR;
00137   tMyDefaultConfig.P.INT_MAJ = CLEAR; /* Isr will be added as the stack grows */
00138   tMyDefaultConfig.P.DONE = CLEAR;
00139   tMyDefaultConfig.P.ACTIVE = CLEAR;
00140   tMyDefaultConfig.P.START = CLEAR;
00141   
00142   /* Copy values to predetermined INBOXes */
00143   vfnDMAConfig(&tMyDefaultConfig, MAILDELIVERY_INBOX1_DMA_CH);
00144   
00145   /* Configure all other inbox pointers associated to this one */
00146   for(u8Counter = MAILDELIVERY_INBOX1_DMA_INDEX_START; u8Counter
00147       <= MAILDELIVERY_INBOX1_DMA_INDEX_END; u8Counter++)
00148   {
00149     gatDSPIInbox[u8Counter] = tMyDefaultConfig;
00150   }
00151 
00152   /* Small mods for the second inbox family */
00153   tMyDefaultConfig.P.MAJORLINKCH = MAILDELIVERY_INBOX2_DMA_CH;
00154   
00155   /* Copy values to predetermined INBOXes */
00156   vfnDMAConfig(&tMyDefaultConfig, MAILDELIVERY_INBOX2_DMA_CH);
00157   for(u8Counter = MAILDELIVERY_INBOX2_DMA_INDEX_START; u8Counter
00158       <= MAILDELIVERY_INBOX2_DMA_INDEX_END; u8Counter++)
00159   {
00160     gatDSPIInbox[u8Counter] = tMyDefaultConfig;
00161   }
00162 
00163   /* Remember which DMA we're using */
00164   gu8InboxDMA = MAILDELIVERY_INBOX1_DMA_CH;
00165   gu8InactiveInboxDMA = MAILDELIVERY_INBOX2_DMA_CH;
00166   
00167   /* Config DMAMux to go along with it */
00168   vfnDMAMUXInit(gu8InboxDMA, DMA_SOURCE_DSPI0_RX, CLEAR, TRUE);
00169   
00170   return (CLEAR);
00171 }
00172 /*
00173  ******************************************************************************
00174  * vfnMailboxInit
00175  ******************************************************************************
00176  */
00177 void vfnMailboxInit(void)
00178 {
00179   /* Start by initializing outboxes */
00180   /* Erase count - contents is not relevant as it will be overwritten */
00181   gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_1] = CLEAR;
00182   gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_2] = CLEAR;
00183   
00184   /* First active Mailbox is the first half */
00185   gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_1;
00186   gi8MailboxActiveInboxOffset  = MAILBOX_ACTIVE_INBOX_IS_1;
00187   
00188   return;
00189 }
00190 
00191 /*
00192  ******************************************************************************
00193  * u8fnMailboxAppendToInbox
00194  ******************************************************************************
00195  */
00196 uint8_t u8fnMailboxAppendToInbox(const uint16_t* pu16MsgResponse,
00197                                  uint16_t u16Size)
00198 {
00199   TCD_t*   ptCurrentTCD;
00200   TCD_t*   ptPreviousTCD;
00201   
00202   /* We need to find which registers we're modifying */
00203   if(MAILBOX_ACTIVE_INBOX_IS_1 == gi8MailboxActiveInboxOffset)
00204   {
00205     /* Modifying directly the DMA, no previous channel, start count for */
00206     /* gi8MailboxActiveInboxOffset.                                     */
00207     ptCurrentTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX1_DMA_CH]);
00208     ptPreviousTCD = (TCD_t*)MAILBOX_NO_PREVIOUS_INBOX;
00209     gi8MailboxActiveInboxOffset = MAILDELIVERY_INBOX1_DMA_INDEX_START;
00210   }
00211   else if(MAILBOX_ACTIVE_INBOX_IS_2 == gi8MailboxActiveInboxOffset)
00212   {
00213     /* Modifying directly the DMA, no previous channel, start count for */
00214     /* gi8MailboxActiveInboxOffset.                                     */
00215     ptCurrentTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX2_DMA_CH]);
00216     ptPreviousTCD = (TCD_t*)MAILBOX_NO_PREVIOUS_INBOX;
00217     gi8MailboxActiveInboxOffset = MAILDELIVERY_INBOX2_DMA_INDEX_START;
00218   }
00219   else
00220   {
00221     /* Modifying some location in RAM, and previous channel may come from */
00222     /* different sources.                                                 */
00223     ptCurrentTCD = &gatDSPIInbox[gi8MailboxActiveInboxOffset];
00224     if(MAILDELIVERY_INBOX1_DMA_INDEX_START == gi8MailboxActiveInboxOffset)
00225     {
00226       /* Previous value was in the DMA itself */
00227       ptPreviousTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX1_DMA_CH]);
00228     }
00229     else if(MAILDELIVERY_INBOX2_DMA_INDEX_START == gi8MailboxActiveInboxOffset)
00230     {
00231       /* Previous value was in the DMA itself */
00232       ptPreviousTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX2_DMA_CH]);
00233     }
00234     else
00235     {
00236       /* Previous channel was already in RAM */
00237       ptPreviousTCD = &gatDSPIInbox[gi8MailboxActiveInboxOffset - 1u];
00238     }
00239     /* Increment buffer count */
00240     gi8MailboxActiveInboxOffset++;
00241   }
00242   /* Start by modifying this TCD's number of Major cycles according to u16Size */
00243   ptCurrentTCD->P.CITER = u16Size;
00244   ptCurrentTCD->P.BITER = u16Size;
00245   
00246   /* Link to the pointer */
00247   ptCurrentTCD->P.DADDR = (uint32_t)pu16MsgResponse;
00248   
00249   /* Call the interrupt for when we're done */
00250   ptCurrentTCD->P.INT_MAJ = TRUE;
00251   
00252   /* Clear any existing "DONE" flags */
00253   ptCurrentTCD->P.DONE = CLEAR;
00254   
00255   /* Clear any existing links to load new config after transfer */
00256   ptCurrentTCD->P.DLAST_SGA = CLEAR;
00257   
00258   /* Disable loading any extra registers after this */
00259   ptCurrentTCD->P.E_SG = CLEAR;
00260   
00261   /* Continue only if we're not writing to the original inbox */
00262   if(MAILBOX_NO_PREVIOUS_INBOX != ptPreviousTCD)
00263   {
00264     /* Disable the Isr for the previous CH     */
00265     ptPreviousTCD->P.INT_MAJ = CLEAR;
00266       
00267     /* Enable loading of this info */
00268     ptPreviousTCD->P.E_SG = TRUE;
00269     
00270     /* Make sure that the next register is loaded */
00271     ptPreviousTCD->P.DLAST_SGA = (int32_t)(ptCurrentTCD);
00272   }
00273   else
00274   {
00275     /* Nothing I think... */
00276   }
00277 
00278   return (CLEAR);
00279 }
00280 /*
00281  ******************************************************************************
00282  * u8fnMailboxAppendToDSPIOutbox
00283  ******************************************************************************
00284  */
00285 uint8_t u8fnMailboxAppendToDSPIOutbox(uint8_t u8DSPIInstance, uint8_t u8CS,
00286                                       uint8_t u8ContCS,
00287                                       uint8_t u8EndOfQueueFlag,
00288                                       uint16_t* pu16Msg, uint16_t u16Size)
00289 {
00290   /* Locals */
00291   uint8_t u8Status;
00292   uint32_t u32Message;
00293   u8Status = CLEAR;
00294 
00295   /* Pre-calculate Message */
00296   /* Format as PUSHR for DSPI transfers */
00297   u32Message = FORMAT_PUSHR(u8DSPIInstance, 
00298                             u8CS, 
00299                             u8ContCS, 
00300                             u8EndOfQueueFlag, 
00301                             CLEAR);
00302   
00303   for(; CLEAR < u16Size; u16Size--)
00304   {
00305     /* Append to outbox */
00306     u8Status |= u8fnMailboxAppendToOutbox(
00307         (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]),
00308         u32Message | *pu16Msg);
00309     /* Increment pointer to next value */
00310     pu16Msg++;
00311   }
00312 
00313   return (u8Status);
00314 }
00315 /*
00316  ******************************************************************************
00317  * u8fnMailboxAppendToDSPIOutbox
00318  ******************************************************************************
00319  */
00320 uint8_t u8fnMailboxAppendToCompositeDSPIOutbox(uint8_t u8DSPIInstance1,
00321                                                uint8_t u8DSPIInstance2, 
00322                                                uint8_t u8CS,
00323                                                uint16_t* pu16Msg1, 
00324                                                uint16_t* pu16Msg2,
00325                                                uint16_t u16SizeAtOrigin)
00326 {
00327   /* Locals */
00328   uint8_t u8Status;
00329   uint32_t u32Message1;
00330   uint32_t u32Message2;
00331   u8Status = CLEAR;
00332   
00333   /* Pre-calculate PUSHR */
00334   u32Message1 = FORMAT_PUSHR(u8DSPIInstance1, u8CS, TRUE, CLEAR, CLEAR);
00335   u32Message2 = FORMAT_PUSHR(u8DSPIInstance2, u8CS, CLEAR, CLEAR, CLEAR);
00336   
00337   for(; CLEAR < u16SizeAtOrigin; u16SizeAtOrigin--)
00338   {
00339     /* Append to outbox */
00340     u8Status |= u8fnMailboxAppendToOutbox(
00341         (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]),
00342         u32Message1 | *pu16Msg1);
00343     /* Redo for Msg 2 */
00344     u8Status |= u8fnMailboxAppendToOutbox(
00345             (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]),
00346             u32Message2 | *pu16Msg2);
00347     /* Increment pointer to next value */
00348     pu16Msg1++;
00349     pu16Msg2++;
00350   }
00351 
00352   return (u8Status);
00353 }
00354 /*
00355  ******************************************************************************
00356  * u8fnAppendToOutbox
00357  ******************************************************************************
00358  */
00359 uint8_t u8fnMailboxAppendToOutbox(uint32_t* pu32Mailbox, uint32_t u32Message)
00360 {
00361   /* Locals */
00362   uint8_t u8Status;
00363   
00364   /* Init locals */
00365   u8Status = CLEAR;
00366   
00367   if(OUTBOX_MAX_BUFFER_CNT > *pu32Mailbox)
00368   {
00369     (*pu32Mailbox)++;
00370     *(pu32Mailbox + *pu32Mailbox) = u32Message;
00371     
00372     /* increment pointers in outbox DMAs */
00373     /* Subtract equivalent values to when the major loop is done */
00374     /* CTAR will be copied to just before data is sent, and therefore is not */
00375     /* tinkered-with here. */
00376     EDMA.TCD[gu8OutboxDMA].BITER++;
00377     EDMA.TCD[gu8OutboxDMA].SLAST -= (4u);
00378   }
00379   else
00380   {
00381     u8Status = MAILBOX_CAPACITY_HAS_BEEN_REACHED;
00382   }
00383   return (u8Status);
00384 }
00385 
00386 /*
00387  ******************************************************************************
00388  * vfnMailDeliveryTriggerOutbox
00389  ******************************************************************************
00390  */
00391 void vfnMailDeliveryTriggerOutbox(uint8_t u8DMAMuxChannel, uint8_t u8Enable)
00392 {
00393   /* Copy BITER to CITER */
00394   EDMA.TCD[u8DMAMuxChannel].CITER = EDMA.TCD[u8DMAMuxChannel].BITER;
00395   
00396   /* Clear DONE flag */
00397   EDMA.TCD[u8DMAMuxChannel].DONE = CLEAR;
00398   
00399   /* Connect Proper EDMA HW Outbox triggers */
00400   EDMA.SERQR.R = u8DMAMuxChannel;
00401   
00402   vfnDMAMUXInit(u8DMAMuxChannel, DMA_SOURCE_DSPI0_TX, CLEAR, u8Enable);
00403   
00404   return;
00405 }
00406 
00407 /*
00408  ******************************************************************************
00409  * vfnMailboxSwitchActiveMailboxes
00410  ******************************************************************************
00411  */
00412 void vfnMailboxSwitchActiveMailboxes(void)
00413 {
00414   /* This routine shall be called when we want to switch the target outbox */
00415   /* to which code will be writing to. As such, it will also switch the    */
00416   /* active DMA channel associated with a given outbox.                    */
00417 
00418   if(MAILDELIVERY_OUTBOX1_DMA_CH == gu8OutboxDMA)
00419   {
00420     /* We're switchting to the second outbox. Clear its count. */
00421     gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_2;
00422     gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_2] = CLEAR;
00423     gi8MailboxActiveInboxOffset = MAILBOX_ACTIVE_INBOX_IS_2;
00424     
00425     gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH;
00426     gu8OutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH;
00427     gu8InactiveInboxDMA = MAILDELIVERY_INBOX1_DMA_CH;
00428     gu8InboxDMA = MAILDELIVERY_INBOX2_DMA_CH;
00429   }
00430   else
00431   {
00432     /* We're switching to the first outbox. Clear it's count */
00433     gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_1;
00434     gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_1] = CLEAR;
00435     gi8MailboxActiveInboxOffset = MAILBOX_ACTIVE_INBOX_IS_1;
00436     
00437     gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH;
00438     gu8OutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH;
00439     gu8InactiveInboxDMA = MAILDELIVERY_INBOX2_DMA_CH;
00440     gu8InboxDMA = MAILDELIVERY_INBOX1_DMA_CH;
00441   }
00442   
00443   /* Reset count before writing anything for output */
00444   EDMA.TCD[gu8OutboxDMA].SLAST = CLEAR;
00445   
00446   return;
00447 }
00448 /*
00449  ******************************************************************************
00450  *
00451  *  End of file.
00452  *
00453  ******************************************************************************
00454  */